#ifndef GAMEOBJECT_H
#define GAMEOBJECT_H

#include "GameComponent.h"
#include "SDL/SDL.h"

#include "util/EatsVars.h"

#include <string>
#include <vector>

using namespace eats_vars;
using namespace std;

namespace eats_core {

/**
 * @brief Entidade de um game. Representação de qualquer coisa que possua algum tipo
 * de comportamento em um game. Possui 1 ou N componentes dentro de si.
 *
 * @autor Eusyar Alves
 */
class GameObject
{
    public:
        GameObject(SDL_Surface * _workingSurf , int _posX = 0, int _posY = 0);
        virtual ~GameObject();

        /**
         * @brief Função responsável por renderizar o objeto. Basicamente passa pela lista
         * de componentes e pede para que ela seja renderizada.
         *
         * @return falso casa algum componente não tenha sido renderizado
         */
        virtual bool render() ;

        /**
         * @brief Função responsável por atualizar a simulação de um objeto. Isso ocorre
         * através da atualização de cada componente desse objeto.
         *
         * @return falso caso algum componente não tenha sido atualizado
         */
        virtual bool update() ;
        virtual bool event()  ;

        virtual bool setUp()  ;

        /**
         * @brief Função responsável por destruir ou simplesmente preparar a desconstrução. Pode correr
         * por todos objetos da lista pedindo para que sejam 'desligados'.
         *
         * @return falso caso algum componente não tenha sido finalizado corretamente. Não sei ainda quando isso acontece
         */
        virtual bool tearDown();

        /**
         * @brief Adiciona determinado comportamento ao objeto.
         *
         * @param comp
         * @autor Eusyar Alves
         */
        void addComponent( GameComponent * comp );

        /**
         * @brief Torna um componente ativo comforme o id.
         *
         * @param id a do item na lista de componentes a ser ativo.
         * @return false caso o id não esteja na lista ou não tenha sido movido corretamente
         */
        bool enableComponent ( string id );

        /**
         * @brief Torna um componente ativo comforme a posição no vetor de componentes presentes.
         *
         * @param posicao do item na lista de componentes a ser ativo.
         * @return false não tenha sido movido corretamente
         */
        bool enableComponent ( int position );

        /**
		 * @brief Torna um componente ativo comforme a referencia no vetor de componentes presentes.
		 *
		 * @param referencia do item na lista de componentes a ser ativo.
		 * @return false não tenha sido movido corretamente ou a referência não exista
		 */
        bool enableComponent ( GameComponent * ref );

        /**
		 * @brief Torna um componente desativado comforme o id.
		 *
		 * @param id a do item na lista de componentes a ser desativado.
		 * @return false caso o id não esteja na lista ou não tenha sido movido corretamente
		 */
        bool disableComponent ( string id );

        /**
		 * @brief Torna um componente desativado comforme a posição no vetor de componentes presentes.
		 *
		 * @param posicao do item na lista de componentes a ser desativado.
		 * @return false não tenha sido movido corretamente
		 */
		bool disableComponent ( unsigned int position );

		/**
		 * @brief Torna um componente desativado comforme a referencia no vetor de componentes presentes.
		 *
		 * @param referencia do item na lista de componentes a ser desativado.
		 * @return false não tenha sido movido corretamente ou a referência não exista
		 */
		bool disableComponent ( GameComponent * ref );

        /**
         * @brief lista com todos os componentes do objeto.
         */
        std::vector<GameComponent *> componentList;

        /**
		 * @brief lista com todos os componentes ativos do objeto.
		 */
        std::vector<GameComponent *> componentEnabledList;

        /**
		 * @brief surpeficie atual do objeto
		 */
        SDL_Surface * workingSurf;


        string _id;
		string _canonical_name;
		bool _isAlive;

    protected:

		Point * position;
		Size * size;

    public:

		int * getX(){
			return &position->x;
		}

		int * getY() {
			return &position->y;
		}

		void setX(int x) {
			position->x = x;
		}

		void setY(int y) {
			position->y = y;
		}

		Point * getPoint() {
			return position;
		}

};

}

#endif // GAMEOBJECT_H
